﻿using System;
using System.IO;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Forms;
using System.Windows.Threading;
using zTalk.Network;
using System.Windows.Media;

namespace zTalk
{
    public partial class Chat : Window
    {
        public UserItem User { get; set; }

        private StreamWriter writer = null;
        private bool firstLine = true;

        public Chat()
        {
            InitializeComponent();

            App.Handler.GetUser += new PacketEventHandler(Handler_GetUser);
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            try
            {
                if (Directory.Exists(".\\logs") == false)
                {
                    Directory.CreateDirectory(".\\logs");
                }
                writer = new StreamWriter(
                    ".\\logs\\" + User.Username + ".txt", true, Encoding.UTF8);
                writer.AutoFlush = true;
            }
            catch { }

            DataContext = User;
            txtMessage.Focus();
            Title = User.Username;
        }

        public void GetUser()
        {
            Packet packet = Packet.Create(
                Opcodes.GET_USER,
                Json.Encode<string[]>(new string[] { User.Username })
            );
            App.Client.SendPacket(packet);
        }

        void Handler_GetUser(object sender, PacketEventArgs ea)
        {
            UserItem u = (UserItem)ea.Result;
            if (u != null)
            {
                Dispatcher.Invoke(DispatcherPriority.Normal, new Action(delegate {
                    User = u;
                    DataContext = u;
                }));
            }
        }

        private void btnSend_Click(object sender, RoutedEventArgs e)
        {
            if (txtMessage.Text.Trim() == string.Empty)
            {
                return;
            }

            MessageProto message = new MessageProto
            {
                Destination = User.Username,
                Source = App.User.Username,
                Text = txtMessage.Text,
                Time = DateTime.Now.ToString("HH:mm:ss"),
            };

            Packet packet = Packet.Create(
                Opcodes.MESSAGE,
                Json.Encode<MessageProto>(message)
            );
            App.Client.SendPacket(packet);

            Message(App.User.Username, txtMessage.Text, DateTime.Now.ToString("HH:mm:ss"));
            txtMessage.Text = string.Empty;
        }

        public void Message(string username, string message, string time)
        {
            if (flowPara.Inlines.Count != 0)
            {
                flowPara.Inlines.Add(new LineBreak());
            }

            log(username, message);

            //Run runTime = new Run("[" + DateTime.Now.ToString("HH:mm:ss") + "] ");
            Run runTime = new Run("[" + time + "] ");
            runTime.FontSize = 11;
            if (username == App.User.Username)
            {
                runTime.Foreground = Brushes.DarkBlue;
            }
            flowPara.Inlines.Add(runTime);

            Run runUser = new Run(username + ": ");
            if (username == App.User.Username)
            {
                runUser.Foreground = Brushes.DarkBlue;
            }
            flowPara.Inlines.Add(runUser);

            foreach (object o in Emoticon.Parse(message))
            {
                if (o is Image)
                {
                    flowPara.Inlines.Add(o as Image);
                }
                else
                {
                    Run r = o as Run;
                    if (username == App.User.Username)
                    {
                        r.Foreground = Brushes.DarkBlue;
                    }
                    flowPara.Inlines.Add(r);
                }
            }

            if (User.Status == UserStatus.OFFLINE && username == App.User.Username)
            {
                Run runOffline = new Run(" (user is offline)");
                runOffline.FontSize = 11;
                runOffline.Foreground = Brushes.Gray;
                flowPara.Inlines.Add(runOffline);
            }

            flowViewer.ScrollToEnd();
        }

        private void Window_Closing(object sender, 
            System.ComponentModel.CancelEventArgs e)
        {
            e.Cancel = true;
            Hide();
        }

        private void Label_MouseDown_Profile(object sender, 
            System.Windows.Input.MouseButtonEventArgs e)
        {
            ViewProfile vp = new ViewProfile();
            vp.User = User;
            vp.Show();
        }

        private void Label_MouseDown_History(object sender, 
            System.Windows.Input.MouseButtonEventArgs e)
        {
            System.Diagnostics.Process.Start(
                new System.Diagnostics.ProcessStartInfo(
                    ".\\logs\\" + User.Username + ".txt"));
        }

        private void log(string username, string message)
        {
            if (writer == null)
            {
                return;
            }

            if (firstLine == true)
            {
                writer.WriteLine("======> Session start: {0}", DateTime.Now);
                firstLine = false;
            }
            writer.WriteLine("[{0}] {1}: {2}",
                DateTime.Now.ToString("HH:mm:ss"), username, message);
        }

        private void Label_MouseDown_SendFile(object sender, 
            System.Windows.Input.MouseButtonEventArgs e)
        {
            OpenFileDialog opf = new OpenFileDialog();
            opf.CheckFileExists = true;
            if (opf.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                FileTransfer ft = new FileTransfer();
                ft.FileInfo = new FileProto
                {
                    FileName = opf.FileName,
                    Size = Convert.ToInt32(new FileInfo(opf.FileName).Length)
                };
                ft.User = User;
                ft.Show();
            }
        }
    }
}
